
/**
 *	TrueMusic - simple java mp3 player
 *
 *	TrueMusic is free software; you can redistribute it
 *	and/or modify it under the terms of the GNU General
 *	Public License as published by the Free Software
 *	Foundation; either version 2 of the License or (at
 *	your option) any later version.
 *
 *	This program is distributed in the hope that it will be
 *	useful but WITHOUT ANY WARRANTY; without even the
 *	implied warranty of the MERCHANTABILITY or FITNESS FOR
 *	A PARTICULAR PURPOSE. See the GNU General Public
 *	License for more details.
 *
 *	Copyright (c)2005-2007 Ryan Macnak <rmacnak@gmail.com>
 */

package com.servequake.truemusic;


import javazoom.jl.player.advanced.AdvancedPlayer;
import org.farng.mp3.*;

import java.io.*;

/**
 * Audio implemented with the JavaLayer decoder.
 */
public class JavaLayerAudio implements Audio, SeekableAudio, Runnable
{
	private String res;

	private int frames = 0; //number of frames in the clip
	private int pos = 0; //the next frame to play
	private int current = 0; //the next frame in the decoder
	private boolean pause = true;

	private Thread runner;
	private AdvancedPlayer p; //the mp3 decoder

	private PlaybackListener l;

	public void load(String res, PlaybackListener l) throws Exception
	{
		load(res,"0",l);
	}

	public void load(String res, String sFrames, PlaybackListener l) throws Exception
	{
		this.res = res;
		this.l = l;

		Integer iFrames = new Integer(sFrames);
		if(iFrames.intValue()>2) this.frames = iFrames.intValue();
		else
		{
			//count frames
			p = new AdvancedPlayer( new FileInputStream(res) );
			while(p.skipFrame()) frames++;
			p.close();
			p = null;
		}
	}

	public String getResource()
	{
		return res;
	}

	public String getTitle()
	{
		return new File(res).getName();
	}

	public String getArtist()
	{
		return "";
	}

	public String getAlbum()
	{
		return "";
	}

	public String getTrack()
	{
		return "";
	}

	public String getGenre()
	{
		return "";
	}

	public String getLyrics()
	{
		return "";
	}

	public int getFrames()
	{
		return frames;
	}

	public String toString()
	{
		return res;
	}

	public String formatName()
	{
		return "Wav";
	}

	public String[] getExtensions()
	{
		return new String[]{".wav"};
	}

	public synchronized void play()
	{
		if(runner==null) (runner = new Thread(this)).start();

		if(!pause) pos = 0;
		else
		{
			pause = false;
			notify();
			l.playbackStarted();
		}
	}

	public synchronized void pause()
	{
		if(runner==null) (runner = new Thread(this)).start();

		pause = !pause;
		if(!pause)
		{
			notify();
			l.playbackStarted();
		}
		else l.playbackStopped();
	}

	public synchronized void stop()
	{
		runner = null;

		l.playbackStopped();
		l.frameCompleted(0);
	}

	public synchronized void seek(int frame)
	{
		this.pos = frame;
	}

	public boolean isPlaying()
	{
		return !pause;
	}

	public void run()
	{
		try
		{
			while(true)
			{
				synchronized(this)
				{
					if(runner==null) break;
					while(pause) wait();

					boolean more = playFrame(pos);
					if( more )
					{
						pos++;
						l.frameCompleted(pos);
					}
					else
					{
						runner = null;
						l.playbackCompleted();
					}
				}

				//System.out.println(pos);
			}
			pos = 0;
			pause = true;
			if(p!=null) p.close();
			p = null;
		}
		catch(Exception e)
		{
			e.printStackTrace();

		}
		finally
		{
			runner = null;
		}
	}

	private boolean playFrame(int frame) throws Exception
	{
		if((p==null) || (frame<current))
		{
			p = new AdvancedPlayer( new FileInputStream(res) );
			current = 0;
		}

		while(frame>current)
		{
			if( !p.skipFrame() ) return false;
			current++;
		}

		javazoom.jl.player.JavaSoundAudioDevice.vol.setValue(l.getVolume());
		current++;
		return p.decodeFrame();
	}
}
